<?php
/**
 * @author all@cosmos-framework.org
 * @copyright (c) 2013 cosmos-framework.org
 * @license http://www.opensource.org/licenses/mit-license.php
 * @link http://cosmos-framework.org/
 * @package cosmos.framework
 * @version 2.0
 */
namespace Cosmos;

class Http {

    public $http_response_header;
    public $header;
    public $host;
    public $password;
    public $port;
    public $protocolVersion;
    public $proxy;
    public $scheme;
    public $timeout;
    public $user;

    public function __construct($baseurl) {

        if (!$baseurl = parse_url($baseurl)) {
            trigger_error('invalid baseurl', E_USER_ERROR);
        }

        if (isset($baseurl['host']))
            $this->host = $baseurl['host'];
        if (isset($baseurl['password']))
            $this->password = $baseurl['password'];
        if (isset($baseurl['port']))
            $this->port = $baseurl['port'];
        if (isset($baseurl['scheme']))
            $this->scheme = $baseurl['scheme'];
        if (isset($baseurl['username'])) {
            $this->user = $baseurl['username'];
        }
    }

    /**
     * @param string $method
     * @param string $path
     * @param string $contents
     * @return string
     */
    public function __invoke($method, $path = null, $contents = null) {

        $this->init($method);

        $l = $this->scheme . '://';
        $l .= $this->user ? $this->user . ':' . $this->password . '@' : '';
        $l .= $this->host;
        $l .= $this->port ? ':' . $this->port : '';
        $l .= $path;

        $c['http']['content'] = $contents;
        $c['http']['method'] = $method;
        $c['http']['ignore_errors'] = 1;

        // options.
        if (isset($this->header))
            $c['http']['header'] = implode("\n", $this->header);
        if (isset($this->protocolVersion))
            $c['http']['protocol_version'] = $this->protocolVersion;
        if (isset($this->proxy))
            $c['http']['proxy'] = $this->proxy;
        if (isset($this->timeout)) {
            $c['http']['timeout'] = $this->timeout;
        }

        // invoke response.
        $this->http_response_header = &$http_response_header;
        return file_get_contents($l, 0, stream_context_create($c));
    }

    /**
     * @param mixed[] &$fields
     */
    public static function body(&$fields) {

        parse_str(file_get_contents('php://input'), $fields);
    }

    /**
     * @param string $path
     * @param string[] $fields
     * @return string
     */
    public function delete($path = null, $fields = null) {

        return $this->__invoke('DELETE', $path . '?' . self::_buildQuery($fields));
    }

    /**
     * @param string $path
     * @param string[] $fields
     * @return string
     */
    public function get($path = null, $fields = null) {

        return $this->__invoke('GET', $path . '?' . self::_buildQuery($fields));
    }

    /**
     * @param string $field
     * @param string $fieldVal
     */
    public function header($field, $fieldVal) {

        $this->header[$field] = $field . ': ' . $fieldVal;
    }

    /**
     * @param string $path
     * @param string[] $fields
     * @return string
     */
    public function post($path = null, $fields = null) {

        return $this->__invoke('POST', $path, self::_buildQuery($fields));
    }

    /**
     * @param string $path
     * @param string[] $fields
     * @return string
     */
    public function put($path = null, $fields = null) {

        return $this->__invoke('PUT', $path, self::_buildQuery($fields));
    }

    /**
     * @param string $method
     */
    protected function init($method) {

        switch ($method) {

            case 'POST' :

                // initialize.
                $this->header('Content-Type', 'application/x-www-form-urlencoded');
                break;
        }
    }

    /**
     * @param string[] $fields
     * @return string
     */
    private static function _buildQuery($fields) {

        return $fields ? http_build_query($fields) : null;
    }

}
